// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "zenstore.h"

#include <zencore/iohash.h>

#include <functional>
#include <unordered_set>

namespace zen {

/** Manage a set of IoHash values
 */

class HashKeySet
{
public:
	void						AddHashToSet(const IoHash& HashToAdd);
	void						AddHashesToSet(std::span<const IoHash> HashesToAdd);
	void						RemoveHashesIf(std::function<bool(const IoHash& CandidateHash)>&& Predicate);
	void						IterateHashes(std::function<void(const IoHash& Hash)>&& Callback) const;
	[[nodiscard]] inline bool	ContainsHash(const IoHash& Hash) const { return m_HashSet.find(Hash) != m_HashSet.end(); }
	[[nodiscard]] inline bool	IsEmpty() const { return m_HashSet.empty(); }
	[[nodiscard]] inline size_t GetSize() const { return m_HashSet.size(); }

	inline void FilterHashes(std::span<const IoHash> Candidates, Invocable<const IoHash&> auto MatchFunc) const
	{
		for (const IoHash& Candidate : Candidates)
		{
			if (ContainsHash(Candidate))
			{
				MatchFunc(Candidate);
			}
		}
	}

	inline void FilterHashes(std::span<const IoHash> Candidates, Invocable<const IoHash&, bool> auto MatchFunc) const
	{
		for (const IoHash& Candidate : Candidates)
		{
			MatchFunc(Candidate, ContainsHash(Candidate));
		}
	}

private:
	// Q: should we protect this with a lock, or is that a higher level concern?
	std::unordered_set<IoHash, IoHash::Hasher> m_HashSet;
};

void hashkeyset_forcelink();

}  // namespace zen
